#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include<QFileDialog>
#include<QIcon>
#include<QDebug>
#include <QVBoxLayout>
#include<pthread.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <QPainter>
#include<fcntl.h>

struct DATA{
    MainWindow *w;
};

void *send_cmd(void *arg) // 定时发送获取时间操作
{
    DATA *data = (DATA *)arg;
    MainWindow *w = data->w;
    int fi_fd = w->fi_fd;
    usleep(500000); // 等待0.5秒
    while(1)
    {


        usleep(500000);
        if(w->flag)
        {
            if(write(fi_fd,"get_time_pos\n", strlen("get_time_pos\n"))==-1)
            {
                perror("write");
            }
        }
    }
}

void *recv_msg(void* arg)
{
    DATA* data = (DATA*)arg;
    MainWindow* w = data->w;
    int fd0 = w->fd0;
    while(1)
    {
        char buf[64]="";
        if(read(fd0, buf, sizeof(buf)) == -1)
        {
            perror("fail to read");
        }
        if(strncmp(buf,"ANS_LENGTH", strlen("ANS_LENGTH")) == 0) // 获取歌曲总时长
        {
            float stime = 0.0f;
            sscanf(buf,"ANS_LENGTH=%f", &stime);
            int totalTime =(int)stime;
            if(totalTime > 0)
            {
                w->totalTime = totalTime;
                int min = w->totalTime / 60;
                int sec = w->totalTime % 60;
                w->currentSongTime = QString("%1:%2").arg(min, 2, 10, QLatin1Char('0'))
                                           .arg(sec, 2, 10, QLatin1Char('0'));
            }
        }
        if(strncmp(buf,"ANS_TIME_POSITION", strlen("ANS_TIME_POSITION")) == 0) // 获取当前运行时间
        {
            float time = 0.0f;
            sscanf(buf,"ANS_TIME_POSITION=%f", &time);
//            qDebug() << time;
            w->runTime=(int)time;
        }
    }
}

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::MainWindow(int fd0,char* fifo_name, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->fd0 = fd0; // 管道读取端O_WRONLY
    if((fi_fd = open(fifo_name, O_WRONLY)) == -1) // 打开有名管道写端
    {
        qDebug() << "fail to open";
        return;
    }

    // 设置图标
    this->setWindowIcon(QIcon(":/picture/timg.jpg"));
    // 设置切换背景图片

    lrcPath =  "/home/edu/work/sys/qtproject/00_code/lyrics/";// "/home/edu/sys/qtproject/00_code/lyrics/"; // 初始化歌词路径
    myListView = ui->songListwidget; // 获取ui对象
    mLrc = new MyLrcHandle; // 歌词对象
    timer = new QTimer(this); // 设置定时器
    runTime = 0; // 初始化运行时间
    lrcTime = 0; // 初始化歌词时间
    minutes = 0; // 初始分钟
    seconds = 0; // 初始秒钟
    flag = false; // 默认没有运行
    currentSongName = ""; // 初始化当前歌曲名
    currentSongTime = ""; // 初始化前歌曲总时长
    volumeFlag = false; // 默认没有被按下音量按钮
    // 设置歌词行高
//    ui->songLrc->setStyleSheet("QListView#songLrc::item { height: 40px; }");
    // 设置 QListWidget 的背景透明
    ui->headListWidget->setStyleSheet("QListWidget { background-color: transparent; color: red}");
    ui->songLrc->setStyleSheet(" QListView { background-color: transparent; }");
    // 禁止编辑
    ui->songLrc->setEditTriggers(QAbstractItemView::NoEditTriggers);

    // 创建数据模型
    songList = new QStandardItemModel(this);
    songLrc = new QStandardItemModel(this);
    // 监听添加文件按钮
    connect(ui->actionOpen,&QAction::triggered, this, &MainWindow::readSongFlies);
    // 监听用户双击的歌曲名
    connect(myListView, &MyListView::selectSongName, this, &MainWindow::getSongName);
    // 监听定时器事件
    connect(timer, SIGNAL(timeout()), this, SLOT(showLrc())); // qt4的方式使用信号槽
    // 监听停止事件
    connect(this, &MainWindow::runTimeStopOrStart, this, &MainWindow::stopRun);
    // 监听点击事件
    connect(ui->runStopBtn, &QPushButton::clicked, this, &MainWindow::stopRun);
    // 进度条拖拽 需要重写
    mySlider = new MySlider(ui->scheduleWidget);
    // 设置自定义类的位置和大小
    mySlider->setGeometry(0, 0, 400, 50); // 设置控件的原始位置和大小
    connect(mySlider, &MySlider::changeValue, this, &MainWindow::dragProgress);
    // 音量拉条
    connect(ui->volumeHSlider, &QSlider::valueChanged, this, &MainWindow::volumeSetting);
    // 音量按钮
    connect(ui->volumeBtn, &QPushButton::clicked, this, &MainWindow::volumeBtn);
    // 音量默认100
    ui->volumeHSlider->setValue(100);


    // 开启线程处理 定时发送时间
    pthread_t tid1, tid2;
    DATA *data;
    data->w = this;
    pthread_create(&tid1, NULL, send_cmd, data);
    pthread_detach(tid1);
    // 开启线程处理 获取时间
    pthread_create(&tid2, NULL, recv_msg, data);
    pthread_detach(tid2);
    // 设置随机种子
    srand(time(NULL));
    // 生成一个在范围[2, 9]内的随机整数 切换背景
    pictureNum = rand() % 7 + 2;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::showLrcHead()
{
    if(!mLrc->getTi().isNull() && !mLrc->getTi().isEmpty())
    {
        QListWidgetItem* item = new QListWidgetItem(QString("歌名: %1").arg(mLrc->getTi()));
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        ui->headListWidget->addItem(item);
    }
    if(!mLrc->getAr().isNull() && !mLrc->getAr().isEmpty())
    {
        QListWidgetItem* item = new QListWidgetItem(QString("歌手: %1").arg(mLrc->getAr()));
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        ui->headListWidget->addItem(item);
    }
    if(!mLrc->getAl().isNull() && !mLrc->getAl().isEmpty())
    {
        QListWidgetItem* item = new QListWidgetItem(QString("专辑: %1").arg(mLrc->getAl()));
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        ui->headListWidget->addItem(item);
    }
    if(!mLrc->getBy().isNull() && !mLrc->getBy().isEmpty())
    {
        QListWidgetItem* item = new QListWidgetItem(QString("制作: %1").arg(mLrc->getBy()));
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        ui->headListWidget->addItem(item);
    }
}

std::list<MyLrc>::iterator MainWindow::findPointFirst()
{
    std::list<MyLrc>::iterator tmpBegin = mLrc->getLrc()->begin();
    std::list<MyLrc>::iterator tmpBegin2 = std::next(tmpBegin);
    std::list<MyLrc>::iterator tmpEnd = mLrc->getLrc()->end();
    std::list<MyLrc>::iterator tmpEnd2 = std::prev(tmpEnd); // 最后一行
    std::list<MyLrc>::iterator tmpEnd3 = std::prev(tmpEnd2); // 倒数第二行

    std::list<MyLrc>::iterator currentLrcPrev2 = std::prev(currentLrc);
    std::list<MyLrc>::iterator currentLrcPrev3 = std::prev(currentLrcPrev2);

    if(currentLrc == tmpBegin) // 如果是一行歌词
        return tmpBegin;
    else if(currentLrc == tmpBegin2) // 当前是第二行歌词
        return tmpBegin;
    else if(currentLrc == tmpEnd2) // 最后一行
    {
        tmpEnd2--;
        tmpEnd2--;
        tmpEnd2--;
        tmpEnd2--;
        return tmpEnd2;
    }else if(currentLrc == tmpEnd3) // 倒数第二行
    {
        tmpEnd3--;
        tmpEnd3--;
        tmpEnd3--;
        return tmpEnd3;
    }
    else
    {
        return currentLrcPrev3; // 其他情况显示当前歌词的前两行
    }
}

void MainWindow::printLrc(std::list<MyLrc>::iterator pd)
{
    std::list<MyLrc>::iterator it = pd;
//    qDebug() << (*pd).second << " " << (*it).lrc;
    for(int i=0;i<5;i++)
    {
        QStandardItem* item = new QStandardItem((*it).lrc);
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        if(it == currentLrc) // 当前唱词颜色不同   
            item->setData(QColor(Qt::red), Qt::TextColorRole);
        else
            item->setData(QColor(Qt::blue), Qt::TextColorRole);

        // 添加新数据
        songLrc->appendRow(item);
        it++;
    }
}

void MainWindow::readSongFlies(bool)
{
    songList->clear(); // 先清空原有链表
    QStringList files = QFileDialog::getOpenFileNames(
                            this,
                            "选择文件",
                            "/home",
                            "Audio Files (*.wav *.mp3 *.ogg *.flac)");

    // 添加新数据
    for(int i=0;i<files.size();i++)
    {
        //准备展示用的数据
        QString songfile = files.at(i); // 处理文件路径
        QStringList songfileSplite = songfile.split("/");
        QString name = songfileSplite.at(songfileSplite.size()-1);
        QStandardItem* item = new QStandardItem(name);
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        songList->appendRow(item);
        // 准备文件和路径映射关系    qDebug() << fileName;
        filesMap.insert(name, songfile);
    }
    myListView->setSongList(songList); // 设置提升窗口显示文件列表
}

void MainWindow::getSongName(QString songName)
{
    currentSongName = songName;
    ui->headListWidget->clear(); // 清理历史数据
    songLrc->clear(); // 先清空原有歌词链表
    // 获取歌曲文件路径
    QMap<QString, QString>::iterator it = filesMap.find(songName);
//    qDebug() << it.key() << " " << it.value();
    // 将mp3后缀改为歌词lrc后缀
    QStringList suffix = it.key().split(".");
    if(mLrc->lrcInit(lrcPath + suffix.at(0) + ".lrc"))
    {
        showLrcHead(); // 展示信息
        currentLrc = mLrc->getLrc()->begin(); // 初始化当前歌词位置
        std::list<MyLrc>::iterator it = currentLrc;
        for(int i=0;i<5;i++) // 初始化最开始的歌词
        {
            QStandardItem* item = new QStandardItem((*it).lrc);
            item->setTextAlignment(Qt::AlignCenter); // item文字居中
            songLrc->appendRow(item);
            it++;
        }
        ui->songLrc->setModel(songLrc);
    }
    else // 没有该歌词文件的情况
    {
        // 展示歌曲名
        QListWidgetItem *item = new QListWidgetItem(suffix.at(0));
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        ui->headListWidget->addItem(item);
    }
    timer->start(500); // 开始计时(单位毫秒)
    runTime = 0; // 重置运行时间
    // 启动播放音乐
    char buf[128] = "";
    sprintf(buf, "loadfile %s\n", it.value().toStdString().c_str());
    if(write(fi_fd, buf, strlen(buf)) == -1)
    {
        qDebug() << "loadfile error";
    }
    flag = true; // 开启运行标志

    // 获取当前歌曲时长
    // 先获取总时间
    if(write(fi_fd,"get_time_length\n", strlen("get_time_length\n"))==-1)
    {
        perror("write");
    }
}

void MainWindow::showLrc()
{
    lrcTime++;
    minutes = runTime / 60; // 每隔60秒
    seconds = runTime % 60;
    // 显示时间
    ui->timeLabel->setText(QString("%1:%2/%3").arg(minutes, 2, 10, QLatin1Char('0'))
                           .arg(seconds, 2, 10, QLatin1Char('0')).arg(currentSongTime));
    // 使用样式表设置文本居中显示
    ui->timeLabel->setAlignment(Qt::AlignCenter);
    // 设置进度条
    double sch = (double)runTime / totalTime * 100;
    mySlider->setValue(sch);

    if(mLrc->getLrc()->size() > 0) // 有歌词需要显示
    {
        if(currentLrc == mLrc->getLrc()->end())
        {
            emit runTimeStopOrStart(); // 如果到了最后
        }
        // 判断时间是否到显示歌词位置
        if(runTime == (*currentLrc).second)
        {
            songLrc->clear(); // 先清空原有链表
            // 判断当前打印歌词的位置
            std::list<MyLrc>::iterator pd = findPointFirst();
            printLrc(pd); // 输出动态歌词

            ui->songLrc->setModel(songLrc); //渲染
            currentLrc++;
        }
    }else
    {
        songLrc->clear(); // 先清空原有链表
        QStandardItem *item = new QStandardItem("暂无歌词信息");
        item->setTextAlignment(Qt::AlignCenter); // item文字居中
        item->setData(QColor(Qt::red), Qt::TextColorRole);
        songLrc->appendRow(item);
        ui->songLrc->setModel(songLrc);
    }
    // 设置按钮暂停图标
    ui->runStopBtn->setIcon(QIcon(":/picture/button_play.png"));
}


void MainWindow::stopRun()
{
    if(flag == true)
    {
        timer->stop();
        action();
        // 设置按钮暂停图标
        ui->runStopBtn->setIcon(QIcon(":/picture/button_pause.png"));
        flag = false;
    }
    else
    {
        // 判断当前歌曲列表是否有可播放的音乐 如果没有可播放的音乐则没有动作
        if(filesMap.isEmpty() || filesMap.size() == 0)
            return;

        // 如果当前播放歌曲为空则选择歌曲列表中第一个歌曲
        if(currentSongName.isNull() || currentSongName.isEmpty())
            emit myListView->selectSongName(filesMap.begin().key());
        // 如果当前可播放的音乐到最后则播放下一首
        if(currentLrc == mLrc->getLrc()->end())
        {
            QMap<QString, QString>::iterator it = filesMap.begin();
            if(filesMap.end().key() == currentSongName)
            {
                emit myListView->selectSongName(filesMap.begin().key()); // 如果是最后一首歌回到第一首歌
            }
            else
            {
                for(;it != filesMap.end(); it++)
                {
                    if(it.key() == currentSongName)
                    {
                        it++;
                        break;
                    }
                }
                emit myListView->selectSongName(it.key());
            }
        }
        timer->start(1000);
        action();
        // 设置按钮继续图标
        ui->runStopBtn->setIcon(QIcon(":/picture/button_play.png"));
        flag = true;
    }
}

void MainWindow::volumeSetting(int value)
{
    // 先设置音量
    char buf[64] = "";
    sprintf(buf, "volume %d 1\n", value);
    if(write(fi_fd,buf,strlen(buf)) == -1) // 设置音量
    {
        perror("write");
    }
}

void MainWindow::volumeBtn()
{
    if(volumeFlag) // 从静音恢复音量
    {
        volumeFlag = false;
        ui->volumeHSlider->setValue(currentVolume);
        ui->volumeBtn->setIcon(QIcon(":/picture/mute1.png"));
    }
    else // 静音
    {
        volumeFlag = true;
        currentVolume = ui->volumeHSlider->value(); // 记录静音前的音量
        ui->volumeHSlider->setValue(1);
        ui->volumeBtn->setIcon(QIcon(":/picture/mute2.png"));
    }

}


void MainWindow::dragProgress(int value)
{
    // 重置当前歌词和时间
    int tmpTime = (int)(value * 0.01 * totalTime); // 计算获取拖拽到的时间
    QString cmd = QString("seek %1\n").arg(tmpTime - runTime); // 计算是进还是退
    if(write(fi_fd,cmd.toStdString().c_str(),strlen(cmd.toStdString().c_str())) == -1) // 控制mplayer快进秒数 如果是负数就快退
    {
        perror("write");
    }
    runTime = tmpTime;
    // 找到大于该时间的第一个歌词
    std::list<MyLrc>::iterator it = mLrc->getLrc()->begin();
    for(;it != mLrc->getLrc()->end(); it++)
    {
        if((*it).second > runTime)
            break;
    }
    currentLrc = it;
    // 重置时间
    minutes = runTime / 60;
    seconds = runTime % 60;
}

void MainWindow::action()
{
    if(write(fi_fd,"pause\n",strlen("pause\n")) == -1) //歌曲暂停
    {
        perror("write");
    }
}

void MainWindow::paintEvent(QPaintEvent *event)
{

    QPainter painter(this);
    // 设置整体背景
    QPixmap pix;
    pix.load(QString(":/picture/%1.jpg").arg(pictureNum));
    painter.drawPixmap(0,0, this->width(), this->height(), pix);
}
